﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ERPStore.Extensions;

using CloudSoft.Extensions;

namespace ERPStore.Diagnostics.Services
{
	public class RewriterService : ERPStore.Web.Services.RewriterService
	{
		private static object m_Lock = new object();

		public RewriterService(ERPStore.Services.ICatalogService catalogService
			, EventBrokR.IPublisher publisher
			, ERPStore.Services.IValidatorService validatorService
			, ERPStore.Logging.ILogger logger
			, ERPStore.Services.ICacheService cacheService)
			: base(catalogService, publisher, logger)
		{
			DbRepository = ERPStore.GlobalConfiguration.Configuration.DependencyResolver.GetService<CloudSoft.Repositories.IRepository<Repositories.DiagnosticDbContext>>();
			ValidatorService = validatorService;
			CacheService = cacheService;
		}

		protected CloudSoft.Repositories.IRepository<Repositories.DiagnosticDbContext> DbRepository { get; private set; }
		protected ERPStore.Services.IValidatorService ValidatorService { get; private set; }
		protected ERPStore.Services.ICacheService CacheService { get; private set; }

		protected IEnumerable<Repositories.Datas.RewriteUrlData> SourceList
		{
			get
			{
				var result = CacheService["Diagnostic:SourceList"] as List<Repositories.Datas.RewriteUrlData>;
				if (result == null)
				{
					lock (m_Lock)
					{
						var query = DbRepository.Query<Repositories.Datas.RewriteUrlData>();
						result = query.ToList();
						CacheService.Add("Diagnostic:SourceList", result, DateTime.Now);
					}
				}
				return result;
			}
		}

		public override System.Web.Mvc.ActionResult RewriteUrl(System.Web.HttpRequestBase Request)
		{
			Repositories.Datas.RewriteUrlData rewrite = null;
			foreach (var item in SourceList.OrderBy(i => i.RewriteOrder.GetValueOrDefault(int.MaxValue)))
			{
				var match = System.Text.RegularExpressions.Regex.Match(Request.RawUrl, item.Source, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
				if (match.Success)
				{
					rewrite = item;
					break;
				}
			}
			if (rewrite != null)
			{
				if (rewrite.Destination.Equals("emptyresult", StringComparison.InvariantCultureIgnoreCase))
				{
					return new System.Web.Mvc.EmptyResult();
				}
				var result = new System.Web.Mvc.RedirectResult(rewrite.Destination, true);
				return result;
			}

			var @event = new Web.Events.PageNotFoundEvent()
			{
				Date = DateTime.Now,
				IP = Request.UserHostAddress,
				Url = Request.RawUrl,
				UserAgent = Request.UserAgent,
				Cookie = (Request.Headers != null) ? Request.Headers["Cookie"] : string.Empty,
				Referer = Request.UrlReferrer,
				ApplicationPath = Request.ApplicationPath,
				Method = Request.HttpMethod,
			};
			EventPublisher.PublishAsync(@event);

			return base.RewriteUrl(Request);
		}

		internal List<ERPStore.Models.BrokenRule> Validate(Models.RewriteUrl model)
		{
			var result = ValidatorService.Validate(model);
			return result;
		}

		internal void SaveRewriteUrl(Models.RewriteUrl model)
		{
			if (model == null)
			{
				throw new ArgumentNullException();
			}
			var br = Validate(model);
			if (!br.IsNullOrEmpty())
			{
				throw new ERPStore.Models.ValidationException(br);
			}

			Repositories.Datas.RewriteUrlData data = null;
			if (model.Id == 0)
			{
				model.CreationDate = DateTime.Now;
				data = AutoMapper.Mapper.Map<Repositories.Datas.RewriteUrlData>(model);
				DbRepository.Insert(data);
			}
			else
			{
				data = DbRepository.Get<Repositories.Datas.RewriteUrlData>(i => i.Id == model.Id);
				data = AutoMapper.Mapper.Map<Models.RewriteUrl, Repositories.Datas.RewriteUrlData>(model, data);
				DbRepository.Update(data);
			}
			model.Id = data.Id;
			CacheService.Remove("Diagnostic:SourceList");
		}
	}
}
